// 3.1 开始session(获取session_id)
use reqwest::Client;
use serde::{Deserialize, Serialize};
use crate::api::get_stream_token::get_stream_token;
use anyhow::{anyhow, Result};
use crate::db::{db_insert::db_insert, db_select::db_select};

/**
 * 从status判断是否已经获取过session_id
 * 每次串流都要重新获取session_id
 * 在串流关闭时, 需要手动将session_status设置为false
 * (一定一定一定(重要的事情说三遍)要程序手动设置session_status, 否则会一直占用session_id, 无法获取正确的session_id)
 * 
 * true: 已经获取过session_id(正在串流或者准备串流)
 *      session_id将从数据库中获取
 * 
 * false: 未获取过session_id(未串流, 或者串流关闭)
 *      session_id需要重新获取
 */
static mut session_id_status: bool = false;

#[derive(Debug, Serialize, Deserialize)]
struct payload {
    clientSessionId: String,
    titleId: String,
    systemUpdateGroup: String,
    settings: Settings,
    serverId: String,
    fallbackRegionNames: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
struct Settings {
    nanoVersion: String,
    enableTextToSpeech: bool,
    highContrast: u8,
    locale: String,
    useIceConnection: bool,
    timezoneOffsetMinutes: i32,
    sdkType: String,
    osName: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct response {
    sessionId: String,
    sessionPath: String,
    state: String,
}
/* 可接受host_id为空, 若为空,则必须session_id_status为true, 并且数据库存在session_id */
pub async fn get_session_id(host_id: Option<String>) -> Result<String> {
    let mut host_id = host_id;
    if(host_id.clone().is_some()) {
        db_insert("host_id", &host_id.clone().unwrap()).await.unwrap();
    }
    if(host_id.is_none()){
        let mut _host_id = String::new();
        if(get_session_id_status()){
            // 判断是否已经处于开启对话的状态, 开启了则返回现在的session_id
            return Ok(db_select("session_id").await.unwrap().value);
        } else if(db_select("host_id").await.is_ok()){
            // 增加判断数据库是否存在host_id
            // 会话未开启, 但是已存储host_id, 则根据存储的host_id获取session_id
            _host_id = db_select("host_id").await.unwrap().value;
        } else {
            // 会话为开启, 且数据库不存在host_id, 则返回错误
            return Err(anyhow!("host_id is none and session_id_status is false and database doesn't save host_id"));
        }
        host_id = Some(_host_id);
    }
    let host_id = host_id.unwrap();
    println!("host_id: {}", host_id);
    

    let device_info = r#"
    {
        "appInfo": {
            "env": {
                "clientAppId": "Microsoft.GamingApp",
                "clientAppType": "native",
                "clientAppVersion": "2203.1001.4.0",
                "clientSdkVersion": "8.5.2",
                "httpEnvironment": "prod",
                "sdkInstallId": ""
            }
        },
        "dev": {
            "hw": {
                "make": "Microsoft",
                "model": "Surface Pro",
                "sdktype": "native"
            },
            "os": {
                "name": "Windows 11",
                "ver": "22631.2715",
                "platform": "desktop"
            },
            "displayInfo": {
                "dimensions": {
                    "widthInPixels": 1920,
                    "heightInPixels": 1080
                },
                "pixelDensity": {
                    "dpiX": 1,
                    "dpiY": 1
                }
            }
        }
    }"#;
    let device_info = device_info.replace("\n", "");

    let payload = payload{
        clientSessionId: "".to_string(),
        titleId: "".to_string(),
        systemUpdateGroup: "".to_string(),
        settings: Settings{
            nanoVersion: "V3;WebrtcTransport.dll".to_string(),
            enableTextToSpeech: false,
            highContrast: 0,
            locale: "en-US".to_string(),
            useIceConnection: false,
            timezoneOffsetMinutes: 120,
            sdkType: "web".to_string(),
            osName: "windows".to_string(),
        },
        serverId: host_id,
        fallbackRegionNames: vec![],
    };
    let payload = serde_json::to_string(&payload).unwrap();

    let client = Client::new();

    let stream_token = get_stream_token().await.unwrap();
    let Authorization = format!("Bearer {stream_token}");

    let response = client.post("https://uks.core.gssv-play-prodxhome.xboxlive.com/v5/sessions/home/play")
        .header("Content-Type", "application/json")
        .header("X-MS-Device-Info", device_info)
        .header("Authorization", Authorization)
        .body(payload)
        .send().await.unwrap();
    let response_code = response.status().as_u16();
    let response_text = response.text().await.unwrap();

    println!("get_session_id response text: {}", response_text);
    match response_code {
        200..=299 => {
            let response:response = serde_json::from_str(&response_text).unwrap();
            let session_id = response.sessionId;
            // 将session_status设置为true, 证明数据库的session_id有效
            set_session_id_status(true);
            db_insert("session_id", &session_id).await.unwrap();
            return Ok(session_id);
        }
        _ => {
            return Err(anyhow!("session_id fail to get, status code:{}", response_code));
        }
    }
    
}

pub fn set_session_id_status(status: bool) {
    unsafe {
        session_id_status = status;
    }
} 

pub fn get_session_id_status() -> bool {
    unsafe {
        return session_id_status;
    }
}